# -*- mode: python ; coding: utf-8 -*-
from PyInstaller.utils.hooks import collect_all
from os.path import join, basename, dirname, exists
from os import walk, makedirs, sep
from shutil import copyfile, rmtree
from platform import system
from subprocess import run

# 初始化空列表
binaries = []
hiddenimports = []
datas = []

# 额外复制 dll 和模块
modules = ['onnxruntime', 'psutil']
for module in modules: 
    tmp_ret = collect_all(module)
    binaries += tmp_ret[1]
    hiddenimports += tmp_ret[2]

# 添加数据文件 (不包括config.py，它需要作为外部可修改文件)
data_files = [
    ('core_server.py', '.'),
    ('core_client.py', '.'),
    ('hot-en.txt', '.'),
    ('hot-zh.txt', '.'),
    ('hot-rule.txt', '.'),
    ('keywords.txt', '.'),
    ('logging_config.yaml', '.'),
    ('readme.md', '.'),
]

# 需要复制到dist目录但不打包到exe内的文件
external_files = [
    'config.py',  # 用户可修改的配置文件
]

# 添加资源文件夹
for root, dirs, files in walk('assets'):
    for file in files:
        src_path = join(root, file)
        dst_path = root
        datas.append((src_path, dst_path))


# 添加必要的数据文件到datas
for src, dst in data_files:
    if exists(src):
        datas.append((src, dst))

a_1 = Analysis(
    ['start_server.py'],
    pathex=[],
    binaries=binaries,
    datas=datas,
    hiddenimports=hiddenimports,
    hookspath=[],
    hooksconfig={},
    runtime_hooks=['build_hook.py'] if exists('build_hook.py') else [],
    excludes=['IPython', 'PIL', 
              'PySide6', 'PySide2', 'PyQt5', 
              'matplotlib', 'wx', 
              'funasr', 'pydantic', 'torch', 
              ],
    noarchive=False,
)

a_2 = Analysis(
    ['start_client.py'],
    pathex=[],
    binaries=binaries,
    datas=datas,
    hiddenimports=hiddenimports,
    hookspath=[],
    hooksconfig={},
    runtime_hooks=['build_hook.py'] if exists('build_hook.py') else [],
    excludes=['IPython', 'PIL', 
              'PySide6', 'PySide2', 'PyQt5', 
              'matplotlib', 'wx', 
              'funasr', 'pydantic', 'torch', 
              ],
    noarchive=False,
)


# 排除不要打包的模块
private_module = ['util', 'config', 
                  'core_server', 
                  'core_client', 
                  ]
pure = a_1.pure.copy()
a_1.pure.clear()
for name, src, type in pure:
    condition = [name == m or name.startswith(m + '.') for m in private_module]
    if condition and any(condition):
        ...
    else:
        a_1.pure.append((name, src, type))    # 把需要保留打包的 py 文件重新添加回 a.pure

pure = a_2.pure.copy()
a_2.pure.clear()
for name, src, type in pure:
    condition = [name == m or name.startswith(m + '.') for m in private_module]
    if condition and any(condition):
        ...
    else:
        a_2.pure.append((name, src, type))    # 把需要保留打包的 py 文件重新添加回 a.pure


pyz_1 = PYZ(a_1.pure)
pyz_2 = PYZ(a_2.pure)


exe_1 = EXE(
    pyz_1,
    a_1.scripts,
    [],
    exclude_binaries=True,
    name='start_server',
    debug=False,
    bootloader_ignore_signals=False,
    strip=False,
    upx=True,
    console=True,
    disable_windowed_traceback=False,
    argv_emulation=False,
    target_arch=None,
    codesign_identity=None,
    entitlements_file=None,
    icon=['assets\\icon.ico'] if exists('assets\\icon.ico') else None,
    contents_directory='internal',
)
exe_2 = EXE(
    pyz_2,
    a_2.scripts,
    [],
    exclude_binaries=True,
    name='start_client',
    debug=False,
    bootloader_ignore_signals=False,
    strip=False,
    upx=True,
    console=True,
    disable_windowed_traceback=False,
    argv_emulation=False,
    target_arch=None,
    codesign_identity=None,
    entitlements_file=None,
    icon=['assets\\icon.ico'] if exists('assets\\icon.ico') else None,
    contents_directory='internal',
)

# 直接在dist目录创建可执行文件
coll = COLLECT(
    exe_1,
    a_1.binaries,
    a_1.datas,

    exe_2,
    a_2.binaries,
    a_2.datas,

    strip=False,
    upx=True,
    upx_exclude=[],
    name='.',  # 直接放在dist目录下
)

# 复制外部可修改文件到dist目录
dest_root = 'dist'
for file in external_files:
    if exists(file):
        dest_file = join(dest_root, file)
        copyfile(file, dest_file)

# 复制util文件夹（比较小）
if exists('util'):
    from shutil import copytree
    dest_util = join(dest_root, 'util')
    if exists(dest_util):
        rmtree(dest_util)
    copytree('util', dest_util)

# 为models文件夹创建一个说明文件，并将models保留在原位置
# 用户需要将整个项目文件夹（包含models）一起分发
models_readme = '''# Models Folder Location

The models folder is not included in the dist directory due to its large size.

To use this executable properly:

1. Keep the models folder in the same directory as this dist folder
2. Your folder structure should be:
   YourProject/
   ├── models/                 # Keep this folder here
   ├── dist/
   │   ├── start_server.exe    # Your executables
   │   ├── start_client.exe
   │   └── config.py           # Editable config
   └── other files...

3. Run the executables from the dist folder
4. The program will automatically find the models folder

If you get "models not found" errors, make sure the models folder
is one level up from the dist folder.
'''

readme_file = join(dest_root, 'MODELS_README.txt')
with open(readme_file, 'w', encoding='utf-8') as f:
    f.write(models_readme)

# Create logs directory for logging
logs_dir = join(dest_root, 'logs')
makedirs(logs_dir, exist_ok=True)



